#ifndef TCPCI_H_
#define TCPCI_H_

#include "common.h"

#define PE_STATE_FULL_NAME      0
#define TCPC_LOW_RP_DUTY        (100)       /* 10 % */
#define TCPC_NORMAL_RP_DUTY     (330)       /* 33 % */

#define typec_get_cc1() p_tcpc_dev->typec_remote_cc[0]
#define typec_get_cc2() p_tcpc_dev->typec_remote_cc[1]
#define typec_get_cc_res() \
        (p_tcpc_dev->typec_polarity ? typec_get_cc2() : typec_get_cc1())
#define typec_check_cc1(cc) (typec_get_cc1() == cc)
#define typec_check_cc2(cc) (typec_get_cc2() == cc)
#define typec_check_cc(cc1, cc2) (typec_check_cc1(cc1) && typec_check_cc2(cc2))
#define typec_check_cc_both(res) (typec_check_cc(res, res))
#define typec_check_cc_any(res) (typec_check_cc1(res) || typec_check_cc2(res))
#define typec_is_drp_toggling() (typec_get_cc1() == TYPEC_CC_DRP_TOGGLING)
#define typec_is_cc_open() typec_check_cc_both(TYPEC_CC_VOLT_OPEN)
#define typec_is_cable_only() (typec_get_cc1() + typec_get_cc2() == TYPEC_CC_VOLT_RA)
#define typec_is_sink_with_emark() \
        (typec_get_cc1() + typec_get_cc2() == TYPEC_CC_VOLT_RA + TYPEC_CC_VOLT_RD)
#define typec_is_cc_no_res() (typec_is_drp_toggling() || typec_is_cc_open())

enum TYPEC_CONNECTION_STATE {
    typec_disabled = 0,
    typec_errorrecovery,

    typec_unattached_snk,
    typec_unattached_src,

    typec_attachwait_snk,
    typec_attachwait_src,

    typec_attached_snk,
    typec_attached_src,

#if CONFIG_TYPEC_CAP_TRY_SOURCE
    /* Require : Assert Rp
     * Exit(-> Attached.SRC) : Detect Rd (tPDDebounce).
     * Exit(-> TryWait.SNK) : Not detect Rd after tDRPTry
     */
    typec_try_src,

    /* Require : Assert Rd
     * Exit(-> Attached.SNK) : Detect Rp (tCCDebounce) and Vbus present.
     * Exit(-> Unattached.SNK) : Not detect Rp (tPDDebounce)
     */
    typec_trywait_snk,
    typec_trywait_snk_pe,
#endif

#if CONFIG_TYPEC_CAP_TRY_SINK
    /* Require : Assert Rd
     * Wait for tDRPTry and only then begin monitoring CC.
     * Exit (-> Attached.SNK) : Detect Rp (tPDDebounce) and Vbus present.
     * Exit (-> TryWait.SRC) : Not detect Rp for tPDDebounce.
     */
    typec_try_snk,

    /*
     * Require : Assert Rp
     * Exit (-> Attached.SRC) : Detect Rd (tCCDebounce)
     * Exit (-> Unattached.SNK) : Not detect Rd after tDRPTry
     */
    typec_trywait_src,
    typec_trywait_src_pe,
#endif /* CONFIG_TYPEC_CAP_TRY_SINK */

    typec_audioaccessory,
    typec_debugaccessory,

#if CONFIG_TYPEC_CAP_DBGACC_SNK
    typec_attached_dbgacc_snk,
#endif /* CONFIG_TYPEC_CAP_DBGACC_SNK */

#if CONFIG_TYPEC_CAP_CUSTOM_SRC
    typec_attached_custom_src,
#endif /* CONFIG_TYPEC_CAP_CUSTOM_SRC */

#if CONFIG_TYPEC_CAP_NORP_SRC
    typec_attached_norp_src,
#endif /* CONFIG_TYPEC_CAP_NORP_SRC */

#if CONFIG_TYPEC_CAP_ROLE_SWAP
    typec_role_swap,
#endif /* CONFIG_TYPEC_CAP_ROLE_SWAP */

#if CONFIG_WATER_DETECTION
    typec_water_protection,
#endif /* CONFIG_WATER_DETECTION */
    typec_foreign_object_protection,
    typec_otp,

    typec_unattachwait_pe, /* Wait Policy Engine go to Idle */
};

enum tcpm_vbus_level {
    TCPC_VBUS_SAFE0V,   /* < 0.8V */
    TCPC_VBUS_INVALID,  /* > 0.8V */
    TCPC_VBUS_VALID,    /* > 4V */
};

static inline int tcpci_check_vbus_valid(struct sgm41620_tcpc *tcpc)
{
    return tcpc->vbus_level >= TCPC_VBUS_VALID;
}

int tcpci_alert(void);
bool tcpci_check_vsafe0v(struct sgm41620_tcpc *tcpc);
int tcpci_alert_status_clear(struct sgm41620_tcpc *tcpc, uint32_t mask);
int tcpci_fault_status_clear(struct sgm41620_tcpc *tcpc, uint8_t status);
int tcpci_set_alert_mask(struct sgm41620_tcpc *tcpc, uint32_t mask);
int tcpci_get_alert_mask(struct sgm41620_tcpc *tcpc, uint32_t *mask);
int tcpci_get_alert_status(struct sgm41620_tcpc *tcpc, uint32_t *alert);
int tcpci_get_fault_status(struct sgm41620_tcpc *tcpc, uint8_t *fault);
int tcpci_get_power_status(struct sgm41620_tcpc *tcpc, uint16_t *pw_status);
int tcpci_init(struct sgm41620_tcpc *tcpc, bool sw_reset);
int tcpci_init_alert_mask(struct sgm41620_tcpc *tcpc);

int tcpci_set_cc(struct sgm41620_tcpc *tcpc, int pull);
int tcpci_get_cc(struct sgm41620_tcpc *tcpc);
int tcpci_set_polarity(struct sgm41620_tcpc * tcpc, int polarity);
int tcpci_set_low_rp_duty(struct sgm41620_tcpc *tcpc, bool low_rp);
int tcpci_set_vconn(struct sgm41620_tcpc *tcpc, bool enable);

int tcpci_set_low_power_mode(struct sgm41620_tcpc *tcpc, bool en);

int tcpci_set_msg_header(struct sgm41620_tcpc *tcpc, uint8_t power_role, uint8_t data_role);
int tcpci_set_rx_enable(struct sgm41620_tcpc *tcpc, uint8_t enable);
int tcpci_protocol_reset(struct sgm41620_tcpc *tcpc);
int tcpci_get_message(struct sgm41620_tcpc *tcpc,uint32_t *payload, 
                      uint16_t *head, enum tcpm_transmit_type *type);
int tcpci_transmit(struct sgm41620_tcpc *tcpc, enum tcpm_transmit_type type, 
                   uint16_t header, const uint32_t *data);
int tcpci_set_bist_test_mode(struct sgm41620_tcpc *tcpc, bool en);

int tcpci_source_vbus(struct sgm41620_tcpc *tcpc, uint8_t type, int mv, int ma);
int tcpci_sink_vbus(struct sgm41620_tcpc *tcpc, uint8_t type, int mv, int ma);
int tcpci_disable_vbus_control(struct sgm41620_tcpc *tcpc);
int tcpci_enable_force_discharge(struct sgm41620_tcpc *tcpc, bool en, int mv);
int tcpci_notify_hard_reset_state(struct sgm41620_tcpc *tcpc, uint8_t state);

bool tcpc_typec_is_act_as_sink_role(struct sgm41620_tcpc *tcpc);
int tcpc_typec_handle_cc_change(struct sgm41620_tcpc *tcpc);
int tcpc_typec_handle_pe_pr_swap(struct sgm41620_tcpc *tcpc);
int tcpc_typec_handle_vsafe0v(struct sgm41620_tcpc *tcpc);
bool tcpc_typec_is_cc_open_state(struct sgm41620_tcpc *tcpc);
int tcpci_check_vbus_valid_from_ic(struct sgm41620_tcpc *tcpc);
void tcpci_vbus_level_refresh(struct sgm41620_tcpc *tcpc);
int tcpci_vbus_level_changed(struct sgm41620_tcpc *tcpc);
void tcpci_vbus_level_init(struct sgm41620_tcpc *tcpc, uint16_t power_status);
int tcpc_typec_init(struct sgm41620_tcpc *tcpc, uint8_t typec_role);
int tcpc_typec_handle_timeout(struct sgm41620_tcpc *tcpc, uint32_t timer_id);
int tcpci_dp_status_update(struct sgm41620_tcpc *tcpc, uint32_t dp_status);
int tcpc_typec_disable(struct sgm41620_tcpc *tcpc);
int tcpc_typec_enable(struct sgm41620_tcpc *tcpc);
int tcpci_report_usb_port_changed(struct sgm41620_tcpc *tcpc);
int tcpci_report_power_control(struct sgm41620_tcpc *tcpc, bool en);
int typec_handle_pe_idle(struct sgm41620_tcpc *tcpc);
int tcpc_typec_set_rp_level(struct sgm41620_tcpc *tcpc, uint8_t rp_lvl);
int tcpc_typec_error_recovery(struct sgm41620_tcpc *tcpc);
int tcpc_typec_handle_ps_change(struct sgm41620_tcpc *tcpc, int vbus_level);
#endif /* TCPCI_H_ */

